﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BaffoHat.Core
{
    public class Game
    {
        public Game()
        {
            Status = GameStatus.PlayersConfiguration;
            this.Players = new List<Player>();

            this.Glasses = new Glasses();
            this.Dice = new Dice();
        }

        #region Status
        public GameStatus Status { get; set; }
        #endregion

        #region Players

        public IList<Player> Players { get; private set; }

        private IEnumerator<Player> playersQueue;

        public Player PlayerTurn
        {
            get
            {
                return playersQueue.Current;
            }
        }

        #endregion

        #region Glasses

        public Glasses Glasses { get; private set; }

        public Glass GlassToBeDrunk { get; private set; }
        #endregion

        public IDice Dice { get; set; }

        public void AddPlayer(Player player)
        {
            if (player == null)
                throw new ArgumentNullException("Player cant be null");

            if (Status != GameStatus.PlayersConfiguration)
                throw new InvalidOperationException("Game status does not allow add player");

            Players.Add(player);
        }

        public void StartGame()
        {
            if(Status != GameStatus.PlayersConfiguration)
                throw new InvalidOperationException("Game already start");

            if (Players.Count == 0)
                throw new InvalidOperationException("Players must be one");

            this.playersQueue = Players.GetEnumerator();
            this.playersQueue.MoveNext();

            Status = GameStatus.WaitingDieRoll;
        }

        public DiceFace RollDice()
        {
            if (Status != GameStatus.WaitingDieRoll)
                throw new InvalidOperationException("Impossible roll dice in the courrent state of game");

            //Lancia il dado
            DiceFace diceFace = Dice.Roll();

            //Se il bicchiere è vuoto lo riempie e cambia il turno
            if (Glasses[diceFace].IsEmpty)
            {
                Glasses[diceFace].Fill();

                Status = GameStatus.WaitingDieRoll;

                ChangeTurn();
            }
            else //Se è pieno il giocatore deve bere 
            {
                Status = GameStatus.WaitingDrinks;

                GlassToBeDrunk = Glasses[diceFace];
            }

            return diceFace;
        }

        public void Drink()
        {
            if (Status != GameStatus.WaitingDrinks)
                throw new InvalidOperationException("Impossible drink in the courrent state of game");

            if (GlassToBeDrunk == null)
                throw new InvalidOperationException("No full glass to drink");

            if (GlassToBeDrunk.IsEmpty)
                throw new InvalidOperationException("The glass is emprty");

            GlassToBeDrunk.Empty();

            GlassToBeDrunk = null;

            Status = GameStatus.WaitingDieRoll;

            PlayerTurn.Drink();
        }

        public void DrinkWithoutHat()
        {
            if (Status != GameStatus.WaitingDrinks)
                throw new InvalidOperationException("Impossible drink in the courrent state of game");

            if (GlassToBeDrunk == null)
                throw new InvalidOperationException("No full glass to drink");

            if (GlassToBeDrunk.IsEmpty)
                throw new InvalidOperationException("The glass is emprty");

            GlassToBeDrunk.Empty();

            PlayerTurn.Drink();

            GlassToBeDrunk.Fill();
        }

        private void ChangeTurn()
        {
            Boolean isEndTurn = !playersQueue.MoveNext();

            //Se è la fine del turno riporta al primo giocatore
            if (isEndTurn)
            {
                playersQueue.Reset();
                playersQueue.MoveNext();
            }
        }

    }
}
